package com.hugoo.rpt;

import com.hugoo.core.Conf;
import com.hugoo.core.ConfigurationError;
import com.hugoo.core.db.HSF;
import com.hugoo.core.db.mo.DCV;
import com.hugoo.core.db.mo.Record;
import com.hugoo.core.db.mo.RecordSet;
import com.hugoo.core.util.Logx;
import com.hugoo.core.util.TL;
import com.hugoo.rpt.ds.DataSource;
import com.hugoo.rpt.ds.DbDataSource;
import com.hugoo.rpt.ds.ImpDataSource;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;

/**
 *
 * @author Lovelock.Chan
 */
public abstract class RptPageInfo extends Logx implements PageInfo {
    
    protected String _sid, dbl;
    protected static final String PS = "_ps_";//pageSize
    protected static final String CP = "_cp_";//Current Page Number
    private static final String SORTED = "_rc_";
    private static final String FILTERED = "_md_";
    private static final String PARA_IN = "_para_in_";
    //////////////////////////////
    protected String[][] col;
    protected Map<String, String> columnStyle = new HashMap<String, String>();
    protected File tmpFile;//文本文件
    protected char[] _sort_col;
    protected DataSource ds = null;
    protected Map<String, String> para = new HashMap<String, String>();//传入的参数值
    /////
    private String sql, _rpt_title, md;
    private List<String> filterList = new ArrayList<String>();
    private List<String[]> mdList = new ArrayList<String[]>();
    private Map<String, String> filterInfo = new HashMap<String, String>();
    private Map<String, String> paraColumn = new HashMap<String, String>();//配置的参数列

    public RptPageInfo(String sid, HttpServletRequest request) throws ParamError, ConfigurationError {
        _sid = sid;
        String url = request.getParameter(PARA_IN);
        TL.parsePara(url, para, log);
        ////////////////初始化数据源///////////////////////
        String _dsc_ = request.getParameter("_dsc_");
        log.debug("_dsc_-->" + _dsc_);
        if (TL.isEmpty(_dsc_)) {
            ds = new DataSource(sid, this.getVersion());
        } else if ("DB".equalsIgnoreCase(_dsc_)) {
            ds = new DbDataSource(sid, this.getVersion());
        } else if ("FILE".equalsIgnoreCase(_dsc_)) {
            String scod = para.get("scod");
            if (TL.isEmpty(scod)) {
                ds = new ImpDataSource(sid, this.getVersion());
            } else {//采用动态读取数据库列数据
                log.debug("采用动态列导入模式，现展示报表。");
                ds = new ImpDataSource(sid, this.getVersion(), scod);
            }
        } else if ("FM".equalsIgnoreCase(_dsc_)) {//表单形式
            ds = new ImpDataSource(sid, this.getVersion());
        } else {
            log.info("无效的数据源提供商：【" + _dsc_ + "】");
            ds = new DataSource(sid);
        }
        //初始化数据源
        dbl = ds.getRptDbl();
        ////////////////////////////////////////////////
        //------------初始化排序列部分-----------------
        String sv = request.getParameter(SORTED);//获取排序字段
        if (TL.isEmpty(sv)) {
            _sort_col = "".toCharArray();
        } else {
            _sort_col = sv.toCharArray();
        }
        md = request.getParameter(FILTERED);//获取排序字段
        if (TL.isNotEmpty(md)) {
            String[] x, mt = md.split(",");
            for (String t : mt) {
                x = t.split("\\|");
                mdList.add(x);
            }
        }
        //-------------------------------------------
        _init_para_column(para);//初始化参数列
        _init_column();//初始化配置列
        _init_filter(para);//初始化配置列
        _init_sql();
        _rpt_title = ds.getRptTitle();
    }
    
    @Override
    public String getVersion() {
        String ver = Conf.getAutqProp2(_sid, Conf.RPT._rpt_ver);
        String pver = Conf.getAutqProp2(_sid, Conf.RPT._rpt_ver_para);
        if (TL.isEmpty(ver)) {
            return null;
        }
        if (!TL.isEmpty(pver)) {
            String e, xc[] = pver.split(",");
            for (String x : xc) {
                if (TL.isNotEmpty(x)) {
                    e = para.get(x);
                    if (e == null) {
                        e = "";
                    } else {
                        e = e.replace("'", "''");
                    }
                    ver = TL.replace(ver, ":" + x, e);
                }
            }
        }
        RecordSet<Record> rs = HSF.query("", "select " + ver + " ver from dual");
        if (rs.first()) {
            return rs.getString("VER");
        }
        return null;
    }
    
    public boolean isExpTitle() {//默认是导出标题行的.
        String lx = Conf.getAutqProp2(_sid, Conf.RPT._rpt_exp_need_title);
        if (TL.isEmpty(lx) || "true".equalsIgnoreCase(lx)) {
            return true;
        } else {
            return false;
        }
    }
    
    public boolean haveEnd() {
        String lx = Conf.getAutqProp2(_sid, Conf.RPT._rpt_exp_need_end);
        if (TL.isEmpty(lx) || "true".equalsIgnoreCase(lx)) {
            return true;
        }
        return false;
    }
    
    @Override
    public String getDbl() {//处理数据源
        return dbl;
    }
    
    private String decode(String[] d) {
        if (d.length == 2) {
            return "";
        }
        try {
            return URLDecoder.decode(d[2], "UTF-8");
        } catch (UnsupportedEncodingException ex) {
            log.info("由于转码问题，不能正确的处理转入的参数部分！程序不能正常的工作哦~");
        }
        return "";
    }

    /**
     * 根据传入的参数，初始化查询语句，
     */
    private void _init_sql() throws ConfigurationError {
        //--------------------本处开始处理数据查询部分--------------------
        sql = ds.getSqlTemplate();
        for (String k : paraColumn.keySet()) {
            String v = paraColumn.get(k);
            sql = sql.replaceAll(":" + k, v);
        }

        //--------------------本处开始处理数据过滤部分--------------------
        if (!filterInfo.isEmpty()) {
            String ft = ds.getSqlFilterTemplate();
            if (TL.isEmpty(ft)) {
                throw new ConfigurationError("发现配置存在问题，存在过滤项，未找到合适的模板！");
            }
            for (String f : filterList) {
                if (filterInfo.containsKey(f)) {//若传入的参数值中，存在过滤模板配置的过滤值，直接引用
                    ft = ft.replaceAll(f, filterInfo.get(f));
                } else {
                    ft = ft.replaceAll(f, " 1=1 ");
                }
            }
            //处理外部传入部分
            sql = "select * from (" + sql + ") where " + ft;
        }
        //-------处理排序部分-----------------------

        char r = 'A';
        StringBuilder sb = new StringBuilder(), s2 = new StringBuilder();
        int i;
        String t;
        for (String c : this.col[0]) {
            //处理过滤部分
            for (String[] m : mdList) {
                if (m.length < 2 || m[0].isEmpty()) {
                    continue;
                }
                if (r == m[0].charAt(0)) {
                    t = decode(m);
                    switch (m[1].charAt(0)) {
                        case '0':
                            if (TL.isEmpty(t)) {
                                s2.append("and ").append(c).append(" is  null ");
                            } else {
                                s2.append("and ").append(c).append(" = '").append(t).append("' ");
                            }
                            break;
                        case '1':
                            if (t.matches("^[-]?[0-9]+(.[0-9]+)?")) {
                                s2.append("and to_number(REGEXP_REPLACE(").append(c).append(",'[^0-9.-]','')) <= ").append(t).append(" ");
                            } else {
                                s2.append("and ").append(c).append(" <= '").append(t).append("' ");
                            }
                            break;
                        case '2':
                            if (TL.isEmpty(t)) {
                                s2.append("and ").append(c).append(" is not null ");
                            } else {
                                s2.append("and ").append(c).append(" <> '").append(t).append("' ");
                            }
                            break;
                        case '3':
                            if (t.matches("^[-]?[0-9]+(.[0-9]+)?")) {
                                s2.append("and to_number(REGEXP_REPLACE(").append(c).append(",'[^0-9.-]','')) >= ").append(t).append(" ");
                            } else {
                                s2.append("and ").append(c).append(" >= '").append(t).append("' ");
                            }
                            break;
                        case '4':
                            s2.append("and ").append(c).append(" like '%").append(t).append("%' ");
                            break;
                    }
                    
                }
            }
            //处理排序部分
            for (i = 0; i < _sort_col.length - 1; i = i + 2) {
                if (_sort_col[i] == r) {
                    switch (_sort_col[i + 1]) {
                        case '0':
                            sb.append(",").append(c);
                            break;
                        case '1':
                            sb.append(",").append(c).append(" desc");
                            break;
                    }
                }
            }
            r++;
        }
        if (s2.length() > 1) {
            sql = "select * from (" + sql + ") where 1=1 " + s2.toString();
        }
        if (sb.length() > 1) {
            sql = sql + " order by " + sb.substring(1);
        }
        //-----------处理排序部分完成----------------
    }
    
    public static void main(String[] args) {
        System.out.println("0.1".matches("^[-]?[0-9]+(.[0-9]+)?"));
    }

    /**
     * *
     * 初始化配置声明的参数列
     *
     * @param m
     */
    private void _init_para_column(Map<String, String> m) {
        String ap = ds.getSqlParaColumn();
        if (TL.isEmpty(ap)) {
            return;
        }
        String paraz[] = ap.split(",");
        String pz[];
        for (String p : paraz) {
            pz = p.split(":");
            if (pz.length == 1) {//暂时只提供列参数单一配置模式
                this.paraColumn.put(pz[0], m.get(pz[0]));
            } else {
                //未做相关的处理
            }
        }
        log.info("查询参数匹配传入参数，有效结果集为：" + paraColumn);
    }
    
    private void _init_filter(Map<String, String> m) {
        String apc = ds.getSqlFilterFields();
        if (TL.isEmpty(apc)) {
            return;
        }
        String cols[] = apc.split(",");
        String tmp;
        for (String cl : cols) {
            filterList.add(cl);
            apc = ds.getSqlFilterFieldConfig(Conf.RPT._rpt_sql_filter_fields + "." + cl);
            if (TL.isEmpty(apc)) {
                log.info("发现过滤模板为空，现以过滤掉本项【" + apc + "】");
                continue;
            }
            tmp = m.get(cl);
            if (TL.isNotEmpty(tmp)) {
                apc = apc.replaceAll(":" + cl, tmp);
                filterInfo.put(cl, apc);
            } else {
                log.info("未发现过滤项【" + cl + "】");
            }
        }
    }
    
    private void _init_column() throws ConfigurationError {
        String dci = getDeclareColumnInfo();//使用处理项自定义列
        if (TL.isEmpty(dci)) {
            dci = ds.getRptColumns();//若不存在自定义，使用公共项
        }
        if (TL.isEmpty(dci)) {//return;
            throw new ConfigurationError("无效的显示列配置！");
        }
        String[] cs, cols = dci.split(",");
        List<String> t1 = new ArrayList(), t2 = new ArrayList();
        for (String cl : cols) {
            if (TL.isEmpty(cl)) {
                continue;
            }
            cs = cl.split(":");
            if (cs.length < 1 || TL.isEmpty(cs[0])) {//处理空列
                continue;
            }
            t1.add(cs[0]);
            if (cs.length == 1) {//处理单列
                t2.add(cs[0]);
                continue;
            }
            if (TL.isEmpty(cs[1])) {//处理声明列
                t2.add(cs[0]);
            } else {
                t2.add(cs[1]);
            }
            if (cs.length == 3) {//【列：名：样式】
                this._init_column_style(cs[0], cs[2]);
            } else if (cs.length == 4) {//【列：名：样式：格式】
                //
            }
        }
        if (t1.size() != t2.size()) {//说明处理列数据时，有误
            throw new ConfigurationError("处理列数据时出错，请检查列配置信息！");
        }
        this.col = new String[][]{t1.toArray(new String[0]), t2.toArray(new String[0])};
    }
    
    private void _init_column_style(String col, String style) {
        if (TL.isEmpty(col, style)) {
            return;
        }
        style = style.replaceAll("\\|", " ");
        columnStyle.put(col, style);
    }
    
    public void validateColumn(ResultSetMetaData rsmd) throws SQLException {
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i <= rsmd.getColumnCount(); i++) {
            sb.append(",").append(rsmd.getColumnName(i));
        }
        sb.append(",");
        String l = sb.toString();
        sb = new StringBuilder();
        for (String cl : col[0]) {
            if (l.indexOf("," + cl + ",") == -1) {
                sb.append("配置列【").append(cl).append("】不存在！");
            }
        }
    }

    /**
     * 本处对访问数据库的列的类型进行重构，让其可以正常的转换为文本值类型
     *
     * @param rs
     * @param key
     * @return
     * @throws SQLException
     */
    protected String getValue(ResultSet rs, String key) throws SQLException {
        return DCV.getValue(rs, key);
    }
    
      protected String getValue(ResultSet rs, String key, char f) throws SQLException {
        String t = "";
        try {
            t = this.getValue(rs, key);
            if (TL.isEmpty(t)) {
                return "";
            }
            double k = Double.parseDouble(t.replaceAll("[^0-9.-]", ""));
            switch (f) {
                case 'r':
                    return TL.numFmt(k, TL.NumFmt.DBL2);
                case 's':
                    return TL.numFmt(k, TL.NumFmt.RMB);
                case 'n':
                    return TL.numFmt(k, TL.NumFmt.NUM);
                case 'p':
                    return TL.numFmt(k, TL.NumFmt.PCT);
            }
        } catch (Exception e) {
            e.printStackTrace(System.err);
        }
        return t;
    }

    /**
     * 获取临时文件
     *
     * @return
     * @throws IOException
     */
    public File getTempFile() throws IOException {
        tmpFile = File.createTempFile(UUID.randomUUID().toString(), null);
        return tmpFile;
    }

    /**
     * **
     * 返回查询SQL语句
     *
     * @return
     */
    @Override
    public String getQuerySql() {
        return sql;
    }
    
    public String getTitle() {
        return _rpt_title;
    }
    
    public File getFile() {
        return tmpFile;
    }
    
    protected abstract String getDeclareColumnInfo();
}
